package ge.devfest.hackathon.gg;

import ge.devfest.hackathon.gg.ActivityFetcherService.ActivityFetcherListener;
import ge.devfest.hackathon.gg.ActivityFetcherService.LocalBinder;
import ge.devfest.hackathon.gg.model.Activity;
import ge.devfest.hackathon.gg.model.Activity.Status;

import java.util.List;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class MainActivity extends BaseActivity {

	private static final String TAG = "MainActivity";
	private ListView mDrawerListview;
	private ActionBarDrawerToggle mDrawerToggle;
	private DrawerLayout mDrawerLayout;
	
	private boolean mMapSetup;
	private GoogleMap mMap;

	private boolean mServiceRunning;
	private ActivityFetcherService mFetcherService;
	
	private ServiceConnection mServiceConnection;
	
	private LatLng mTbilisiLatLng = new LatLng(41.703767, 44.793881);
	
	private ActivityFetcherListener mFetcherListener = new ActivityFetcherListener() {
		
		@Override
		public void onFetchCompleted(int errCode, List<Activity> activities) {
			if (errCode == ActivityFetcherService.FETCH_STATUS_OK) {
				LatLng latLng = null;
				clearMap();
				for (Activity act : activities) {
					addActivityOnMap(act);
					if (latLng == null) {
						latLng = new LatLng(act.getLatitude(), act.getLongitude());
					}
				}
				if (mMap != null && latLng != null) {
					mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 13));
				}
			} else {
				switch (errCode) {
				case ActivityFetcherService.FETCH_STATUS_IO_EXCEPTION:
					break;
				case ActivityFetcherService.FETCH_STATUS_JSON_EXCEPTION:
					break;
				case ActivityFetcherService.FETCH_STATUS_UNKNOWN_EXCEPTION:
					break;
				}
			}
			cleanupActivityFetcherService();
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		if (savedInstanceState == null) {
			getSupportFragmentManager()
			.beginTransaction()
			.add(R.id.content_frame, new SupportMapFragment())
			.commit();
		}
		setupDrawer(savedInstanceState != null);
		startAndBindActivityFetcherService();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		mMap = getGoogleMap();
		if (mMap != null) {
			setupMap();
		}
	}
	
	private void setupDrawer(boolean restoring) {
		mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
		mDrawerListview = (ListView) findViewById(R.id.left_drawer);
		mDrawerListview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
		mDrawerListview.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				invalidateMap();
			}
		});
		if (restoring) {
			invalidateMap();
		}
		
		String[] drawerItems = getResources().getStringArray(R.array.drawer_items);
		ArrayAdapter<String> drawerAdapter = new ArrayAdapter<String>(this, R.layout.drawer_list_item_view, drawerItems);
		mDrawerListview.setAdapter(drawerAdapter);
		mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, 0, 0);
		mDrawerLayout.setDrawerListener(mDrawerToggle);
		ActionBar ab = getSupportActionBar();
		ab.setDisplayHomeAsUpEnabled(true);
		ab.setHomeButtonEnabled(true);
	}

	@Override
	protected void onPostCreate(Bundle savedInstanceState) {
		super.onPostCreate(savedInstanceState);
		mDrawerToggle.syncState();
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getSupportMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item != null && item.getItemId() == android.R.id.home && mDrawerToggle.isDrawerIndicatorEnabled()) {
            if (mDrawerLayout.isDrawerVisible(GravityCompat.START)) {
                mDrawerLayout.closeDrawer(GravityCompat.START);
            } else {
                mDrawerLayout.openDrawer(GravityCompat.START);
            }
            return true;
        }
		switch (item.getItemId()) {
		case R.id.new_activity:
			startActivity(ActivityActivity.class);
			return true;
		case R.id.update:
			startAndBindActivityFetcherService();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
	
	private void setupMap() {
		if (!mMapSetup) {
			mMap.setMyLocationEnabled(true);
			mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mTbilisiLatLng, 11));
			mMapSetup = true;
		}
	}
	
	private void startAndBindActivityFetcherService() {
		if (!mServiceRunning) {
			Intent service = new Intent(this, ActivityFetcherService.class);
			startService(service);
			if (bindService(service, getConnection(), 0)) {
				Log.d(TAG, "bound to ActivityFetcherService");
			}
			mServiceRunning = true;
			Log.d(TAG, "startAndBindActivityFetcherService");
		}
	}
	
	private void cleanupActivityFetcherService() {
		if (mFetcherService != null) {
			mFetcherService.setActivityFetcherListener(null);
			mFetcherService = null;
			Log.i(TAG, "unregistered activityFetcherListener");
		}
		if (mServiceConnection != null) {
			unbindService(mServiceConnection);
			mServiceConnection = null;
			Log.i(TAG, "unbind serviceCOnnection");
		}
		Log.d(TAG, "cleanupActivityFetcherService");
		mServiceRunning = false;
	}
	
	private void invalidateMap() {
		if (mMap != null) {
			mMap.clear();
			List<Activity> activities = GuerrillaApplication.getInstance().list();
			for (Activity a : activities) {
				Status s = a.getStatus();
				if (s != null && mDrawerListview.isItemChecked(s.ordinal())) {
					addActivityOnMap(a);
				}
			}
		}
	}
	
	private void addActivityOnMap(Activity activity) {
		if (mMap != null) {
			MarkerOptions mo = toMarkerOptions(activity);
			mMap.addMarker(mo);
			GuerrillaApplication.getInstance().putActivity(activity.getId(), activity);
			mMap.setOnMarkerClickListener(new OnMarkerClickListener() {
				
				@Override
				public boolean onMarkerClick(Marker marker) {
					return false;
				}
			});
		}
	}
	
	private void clearMap() {
		if (mMap != null) {
			mMap.clear();
			GuerrillaApplication.getInstance().clearActivityCache();
		}
	}
	
	private MarkerOptions toMarkerOptions(Activity activity) {
		LatLng latLng = new LatLng(activity.getLatitude(), activity.getLongitude());
		int icon = R.drawable.ic_launcher;
		switch (activity.getStatus()) {
		case PLANTED:
			icon = R.drawable.ic_planted;
			break;
		case TO_BE_CLEANED:
			icon = R.drawable.ic_to_be_cleaned;
			break;
		case TO_BE_PLANTED:
			icon = R.drawable.ic_to_be_planted;
			break;
		case TO_BE_WATERED:
			icon = R.drawable.ic_to_be_watered;
			break;
		case CLEANED:
			icon = R.drawable.ic_cleaned;
			break;
		case WATERED:
			icon = R.drawable.ic_water;
			break;
		default:
			break;
		}
		return new MarkerOptions()
		.title(activity.getTitle())
		.position(latLng)
		.icon(BitmapDescriptorFactory.fromResource(icon));
	}

	private GoogleMap getGoogleMap() {
		SupportMapFragment mf = getMapFragment();
		return mf != null ? mf.getMap() : null;
	}

	private SupportMapFragment getMapFragment() {
		FragmentManager fm = getSupportFragmentManager();
		return (SupportMapFragment) fm.findFragmentById(R.id.content_frame);
	}
	
	private ServiceConnection getConnection() {
		if (mServiceConnection == null) {
			mServiceConnection = new ServiceConnection() {

				@Override
				public void onServiceConnected(ComponentName name, IBinder service) {
					mFetcherService = ((LocalBinder)service).getService();
					mFetcherService.setActivityFetcherListener(mFetcherListener);
					Log.d(TAG, "onServiceConnected");
				}

				@Override
				public void onServiceDisconnected(ComponentName name) {
				}
				
			};
		}
		return mServiceConnection;
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
		cleanupActivityFetcherService();
	}

}
